package com.jzhao.jpre.base.queue;

import EDU.oswego.cs.dl.util.concurrent.BoundedLinkedQueue;

import com.jzhao.jpre.base.Assembler;
import com.jzhao.jpre.threadpool.ThreadPool;

public class SyncTaskQueue {
	private int capacity = 0;
	private BoundedLinkedQueue taskQueue = null;
	private boolean isOpen = false;
	private Thread taskListener = null;

	public SyncTaskQueue(int capacity) {
		this.capacity = capacity;
		start();
	}

	public SyncTaskQueue() {
		this(100);
	}

	public int capacity() {
		return capacity;
	}

	public boolean isEmpty() {
		return taskQueue.isEmpty();
	}

	public synchronized boolean putTask(Runnable task) {
		try {
			if (isOpen) {
				taskQueue.put(task);
				return true;
			}
			return false;
		} catch (InterruptedException ie) {
			System.out.println(ie);
			return false;
		}
	}

	class TaskListener implements Runnable {
		public void run() {
			Runnable task = null;
			while (!Thread.currentThread().isInterrupted()) {
				try {
					task = (Runnable) taskQueue.take();
					ThreadPool threadPool = (ThreadPool) Assembler
							.getInstance("ThreadPool");
					threadPool.getPool().execute(new TaskProcess(task));
				} catch (RuntimeException re) {
					System.out.println(re);
					if (re.getMessage().equals("Pool is blocked"))
						synchronized (task) {
							task.notify();
						}
				} catch (InterruptedException ie) {
					System.out.println(ie);
					if (!isOpen) {
						taskQueue = null;
						break;
					}
				}
			}
		}
	}

	class TaskProcess implements Runnable {
		Runnable runnable = null;

		public TaskProcess(Runnable runnable) {
			this.runnable = runnable;
		}

		public void run() {
			runnable.run();
			synchronized (runnable) {
				runnable.notify();
			}
		}
	}

	public void start() {
		if (!isOpen) {
			taskQueue = new BoundedLinkedQueue(this.capacity);
			isOpen = true;
			taskListener = new Thread(new TaskListener());
			taskListener.start();
		}
	}

	public void stop() {
		if (isOpen) {
			isOpen = false;
			while (!taskQueue.isEmpty()) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException ie) {
					System.out.println(ie);
				}
			}
			taskQueue = null;
			taskListener.interrupt();
			taskListener = null;
		}
	}
}
